#include <string.h>
#include <stdlib.h>
#include <pthread.h>
#include <struct.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

void *mythread_control(void *arg); //控制指令的线程函数 声明
void modbus_review();//modbus发送给上报进程序列化消息
float read_modbus_data(int sockfd,unsigned char *buf);   //处理modbus采集的数据
float read_modbus_data_f(int sockfd,unsigned char *buf); //处理modbus采集的数据 float型
int read_modbus_data_i(int sockfd,unsigned char *buf);  //处理modbus采集的数据 int型
void cJSON_modbus_printf(int fd);  //cJSON协议处理

//发送命令缓冲区
//温度
unsigned char send_buf_tem[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x04, 0x00, 0x00, 0x00, 0x02};
//湿度
unsigned char send_buf_hum[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x04, 0x00, 0x02, 0x00, 0x02};
//空调开关
unsigned char send_buf_air_switch_read[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01};
unsigned char send_buf_air_switch0_write[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00};
unsigned char send_buf_air_switch1_write[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0x00, 0xFF, 0x00};
//空调温度控制
unsigned char send_buf_air_tem_read[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02};
unsigned char send_buf_air_tem_write[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x11, 0x01, 0x10, 0x00, 0x00, 0x00, 0x02, 0x04,0x00,0x00,0x00,0x00};
//灯开关
unsigned char send_buf_light_switch_read[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01};
unsigned char send_buf_light0_write[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0x01, 0x00, 0x00};
unsigned char send_buf_light1_write[128] = {0x02, 0xb7, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0x01, 0xFF, 0x00};

//共享内存共用结构体
static struct shm_param para;

//数据发送和接受的结构体定义
static struct msg_struct send_msg;
static struct msg_struct recv_msg;

//定义内核链表结构体
static struct mb_node_list head;

//modbus发送给上报进程序列化消息
void modbus_review()
{
	//定义发送的消息序列化
	cJSON *root3 = cJSON_CreateObject();
	//发送给数据上报进程的消息序列化
	cJSON_AddItemToObject(root3, "type", cJSON_CreateNumber(2));
	cJSON_AddItemToObject(root3, "result", cJSON_CreateNumber(0));
	cJSON_AddItemToObject(root3, "msg", cJSON_CreateString("控制成功"));
	strcpy(send_msg.msg_val, cJSON_Print(root3));
	if(msg_queue_send("msg_report",&send_msg,sizeof(send_msg),0)<0)
	{
		printf("send error\n");
	}
}

// //float转16进制
// void float_to_x(int sockfd,float float_data)
// {
// 	printf("%.1f\n",float_data);
// 	unsigned char * x_data = (unsigned char*)&float_data;
// 	for(int i = 0; i<4; i++) 
// 	{
// 		printf("0x%2X,", x_data[i]);
// 	}
// 	putchar(10);
// 	float *p = send_buf_air_tem_write + 13; //将指针偏移到数据位置
// 	*p = *x_data;
// 	send(sockfd, send_buf_air_tem_write , 17, 0);
// }

//控制指令的线程函数
void *mythread_control_1(void *arg)
{
	printf("control\n");
	int sockfd = *(int *)arg;
	int recv_data;
	int air_data[4] = {0};

	while (1)
	{
		//接收消息
		if (msg_queue_recv("mb_msg", &recv_msg, sizeof(recv_msg), 0, 0) > 0)
		{
			printf("recv from msg_report data = %s\n", recv_msg.msg_val);
			printf("recv from msg_report key = %d\n", recv_msg.key);
		}
		else
		{
			perror("recv error:");
		}

		switch(recv_msg.key)
		{
			case 101:
				modbus_review();
				break;
			case 102:
				modbus_review();
				break;
			case 103:
				recv_data = recv_msg.msg_val[1]-48;
				printf("%d\n",recv_data);
				if(recv_data == 1)
				{
					send(sockfd, send_buf_air_switch1_write , 12, 0);
				}
				else if(recv_data == 0)
				{
					send(sockfd, send_buf_air_switch0_write , 12, 0);
				}
				modbus_review();
				break;
			case 104:
				// float_to_x(sockfd,87.4);
				modbus_review();
				break;
			case 105:
				recv_data = recv_msg.msg_val[1]-48;
				printf("%d\n",recv_data);
				if(recv_data == 1)
				{
					send(sockfd, send_buf_light1_write , 12, 0);
				}
				else if(recv_data == 0)
				{
					send(sockfd, send_buf_light0_write , 12, 0);
				}
				modbus_review();
				break;
		}
	}
	pthread_exit(NULL);
}

//控制指令的线程函数
void *mythread_control_2(void *arg)
{
	printf("control\n");
	int sockfd = *(int *)arg;
	int recv_data;
	int air_data[4] = {0};

	while (1)
	{
		//接收消息
		if (msg_queue_recv("mb_msg", &recv_msg, sizeof(recv_msg), 0, 0) > 0)
		{
			printf("recv from msg_report data = %s\n", recv_msg.msg_val);
			printf("recv from msg_report key = %d\n", recv_msg.key);
		}
		else
		{
			perror("recv error:");
		}

		switch(recv_msg.key)
		{
			case 101:
				modbus_review();
				break;
			case 102:
				modbus_review();
				break;
			case 103:
				recv_data = recv_msg.msg_val[1]-48;
				printf("%d\n",recv_data);
				if(recv_data == 1)
				{
					send(sockfd, send_buf_air_switch1_write , 12, 0);
				}
				else if(recv_data == 0)
				{
					send(sockfd, send_buf_air_switch0_write , 12, 0);
				}
				modbus_review();
				break;
			case 104:
				// float_to_x(sockfd,87.4);
				modbus_review();
				break;
			case 105:
				recv_data = recv_msg.msg_val[1]-48;
				printf("%d\n",recv_data);
				if(recv_data == 1)
				{
					send(sockfd, send_buf_light1_write , 12, 0);
				}
				else if(recv_data == 0)
				{
					send(sockfd, send_buf_light0_write , 12, 0);
				}
				modbus_review();
				break;
		}
	}
	pthread_exit(NULL);
}
//控制指令的线程函数
void *mythread_control_3(void *arg)
{
	printf("control\n");
	int sockfd = *(int *)arg;
	int recv_data;
	int air_data[4] = {0};

	while (1)
	{
		//接收消息
		if (msg_queue_recv("mb_msg", &recv_msg, sizeof(recv_msg), 0, 0) > 0)
		{
			printf("recv from msg_report data = %s\n", recv_msg.msg_val);
			printf("recv from msg_report key = %d\n", recv_msg.key);
		}
		else
		{
			perror("recv error:");
		}

		switch(recv_msg.key)
		{
			case 101:
				modbus_review();
				break;
			case 102:
				modbus_review();
				break;
			case 103:
				recv_data = recv_msg.msg_val[1]-48;
				printf("%d\n",recv_data);
				if(recv_data == 1)
				{
					send(sockfd, send_buf_air_switch1_write , 12, 0);
				}
				else if(recv_data == 0)
				{
					send(sockfd, send_buf_air_switch0_write , 12, 0);
				}
				modbus_review();
				break;
			case 104:
				// float_to_x(sockfd,87.4);
				modbus_review();
				break;
			case 105:
				recv_data = recv_msg.msg_val[1]-48;
				printf("%d\n",recv_data);
				if(recv_data == 1)
				{
					send(sockfd, send_buf_light1_write , 12, 0);
				}
				else if(recv_data == 0)
				{
					send(sockfd, send_buf_light0_write , 12, 0);
				}
				modbus_review();
				break;
		}
	}
	pthread_exit(NULL);
}

//处理modbus采集的数据 float型
float read_modbus_data_f(int sockfd,unsigned char *buf)
{
	//接收缓冲区
	unsigned char recv_buf[128] = {0};
	send(sockfd, buf, 12, 0);
	int ret2 = recv(sockfd, recv_buf, 13, 0);
	if (ret2 < 0)
	{
		perror("recv err");	
	}
	//解析出需要的数据来
	float *p = recv_buf + 9; //将指针偏移到数据位置
	float data = *p;
	return data;		
}

//处理modbus采集的数据 int型
int read_modbus_data_i(int sockfd,unsigned char *buf)
{
	//接收缓冲区
	unsigned char recv_buf[128] = {0};
	send(sockfd, buf, 12, 0);
	int ret2 = recv(sockfd, recv_buf, 13, 0);
	if (ret2 < 0)
	{
		perror("recv err");	
	}
	//解析出需要的数据来
	int *p = recv_buf + 9; //将指针偏移到数据位置
	int data = *p;
	return data;		
}

void cJSON_modbus_printf(int fd)
{
	INIT_LIST_HEAD(&head.list); //初始化链表
	//反序列操作
	char buf[1090];
	cJSON *root = NULL;
	cJSON *item = NULL;
	cJSON *array = NULL;
	cJSON *temp = NULL;
	//打开json文件
	fd = open("../res/node.json", O_RDONLY);
	if (fd == -1)
	{
		perror("open err.");
		return ;
	}
	size_t ret = read(fd, buf, 1090);
	if (ret < 0)
	{
		perror("read err.");
		return ;
	}

	root = cJSON_Parse(buf);
	if (!root)
	{
		printf("Error before: [%s]\n", cJSON_GetErrorPtr());
	}
	else
	{
		item = cJSON_GetObjectItem(root, "modbus");
		printf("%s\n", cJSON_Print(item));

		item = cJSON_GetObjectItem(root, "modbus");
		array = cJSON_GetObjectItem(item, "data");
		for (int i = 0; i < cJSON_GetArraySize(array); i++)
		{
			temp = cJSON_GetArrayItem(array, i);
			//使用循环为JSON中的数组中的值进行赋值
			struct mb_node_list *mb = (struct mb_node_list *)malloc(sizeof(struct mb_node_list));
			mb->node.key = cJSON_GetObjectItem(temp, "key")->valueint;
			strcpy(mb->node.name, cJSON_Print(cJSON_GetObjectItem(temp, "name")));
			mb->node.addr = cJSON_GetObjectItem(temp, "addr")->valueint;
			mb->node.type = cJSON_GetObjectItem(temp, "type")->valueint;
			list_add_tail(&mb->list, &head.list);
		}
	}
}

//创建socket函数
int create_socket(int sockfd,int port)
{
	int addrlen = sizeof(struct sockaddr);
	struct sockaddr_in serveraddr;

	// 1创建一个套接字--socket
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sockfd < 0)
	{
		perror("socket err");
		exit(-1);
	}
	printf("socket ok\n");
	// 2指定服务器地址--sockaddr_in
	bzero(&serveraddr, addrlen);
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr("192.168.31.133");
	serveraddr.sin_port = htons(port);

	// 3连接服务器--connect
	if (connect(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0)
	{
		perror("connect err");
		exit(-1);
	}
	printf("connect ok\n");
	return sockfd;
}

int main(int argc, char *argv[])
{
	printf("*******************共享内存存放数据*************************\n");
	int fd;
	//共享内存创建
	int shm_ret = -1;
	shm_ret = shm_init(&para, "shm_edge", sizeof(struct std_node) * 5);
	if (shm_ret < 0)
	{
		return -1;
	}

	struct std_node *node = shm_getaddr(&para);
	if (node == NULL)
	{
		return -1;
	}

	cJSON_modbus_printf(fd);

	printf("********************创建socket连接***********************\n");
	//定义变量
	int sockfd1,sockfd2,sockfd3;
	int port1 = 502;
	int port2 = 503;
	int port3 = 504;
	
	sockfd1 = create_socket(sockfd1,port1);
	sockfd2 = create_socket(sockfd2,port2);
	sockfd3 = create_socket(sockfd3,port3);

	printf("***********************线程函数创建发送和接收消息*******************\n");
	pthread_t tid_control; //控制指令线程

	if (pthread_create(&tid_control, NULL, mythread_control_1, (void *)&sockfd1) != 0)
	{
		perror("pthread_create1 err.");
		return -1;
	}
	if (pthread_create(&tid_control, NULL, mythread_control_2, (void *)&sockfd2) != 0)
	{
		perror("pthread_create1 err.");
		return -1;
	}
	if (pthread_create(&tid_control, NULL, mythread_control_3, (void *)&sockfd3) != 0)
	{
		perror("pthread_create1 err.");
		return -1;
	}

	float tem_data,hum_data,air_tem;
	int air_on_off,light_on_off; //空调温度开关控制和灯开关控制
	while(1)
	{
		tem_data = read_modbus_data_f(sockfd1,&send_buf_tem);
		node[0].key = 101;
		node[0].new_val.f_val = tem_data;
		node[0].ret = 0;
		printf("tem = %.2f\n",node[0].new_val.f_val);
		
		hum_data = read_modbus_data_f(sockfd1,&send_buf_hum);
		node[1].key = 102;
		node[1].new_val.f_val = hum_data;
		node[1].ret = 0;
		printf("hum = %.2f\n",node[1].new_val.f_val);

		air_on_off = read_modbus_data_i(sockfd2,&send_buf_air_switch_read);
		node[2].key = 103;
		node[2].new_val.b_val = air_on_off;
		node[2].ret = 0;
		printf("air_switch = %d\n",node[2].new_val.b_val);
			
		air_tem = read_modbus_data_f(sockfd3,&send_buf_air_tem_read);
		node[3].key = 104;
		node[3].new_val.f_val = air_tem;
		node[3].ret = 0;
		printf("air_tem = %.2f\n",node[3].new_val.f_val);

		light_on_off = read_modbus_data_i(sockfd2,&send_buf_light_switch_read);
		node[4].key = 105;
		node[4].new_val.b_val = light_on_off;
		node[4].ret = 0;
		printf("light_switch = %d\n",node[4].new_val.b_val);

		sleep(3);
	}

	pthread_join(tid_control, NULL);

	close(fd);
	// 5关闭连接--close
	close(sockfd1);
	close(sockfd2);
	close(sockfd3);
	return 0;
}


